#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import logging
from typing import Dict, Any, List, Callable, Optional
import re
import time

logger = logging.getLogger("规则引擎")


class Rule:
    """规则基类"""
    def __init__(self, name: str, description: str, priority: int = 0):
        self.name = name
        self.description = description
        self.priority = priority
        self.last_checked = 0
    
    def check(self, context: Dict[str, Any]) -> bool:
        """检查规则是否通过"""
        raise NotImplementedError("子类必须实现check方法")
    
    def get_violation_message(self) -> str:
        """获取规则违反时的提示信息"""
        return f"规则 '{self.name}' 被违反: {self.description}"


class ConfidentialityRule(Rule):
    """保密性规则"""
    def __init__(self, description: str = "保护用户隐私和敏感信息"):
        super().__init__("confidentiality", description, priority=100)
        # 简单的敏感信息正则表达式
        self.sensitive_patterns = [
            r'\b\d{17}[\dXx]\b',  # 身份证号
            r'\b1[3-9]\d{9}\b',   # 手机号
            r'\b\d{16,19}\b',     # 银行卡号
            r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'  # 邮箱
        ]
    
    def check(self, context: Dict[str, Any]) -> bool:
        """检查是否包含敏感信息"""
        self.last_checked = time.time()
        
        # 检查文本内容
        text = context.get("text", "")
        for pattern in self.sensitive_patterns:
            if re.search(pattern, text):
                logger.warning(f"检测到敏感信息: {pattern}")
                return False
        
        # 检查是否存储了敏感字段
        sensitive_fields = context.get("sensitive_fields", [])
        for field in sensitive_fields:
            if field in context:
                logger.warning(f"检测到敏感字段: {field}")
                return False
        
        return True


class AccuracyRule(Rule):
    """准确性规则"""
    def __init__(self, description: str = "确保系统输出准确可靠"):
        super().__init__("accuracy", description, priority=90)
        self.min_confidence = 0.7
    
    def check(self, context: Dict[str, Any]) -> bool:
        """检查输出的准确性和置信度"""
        self.last_checked = time.time()
        
        # 检查置信度
        confidence = context.get("confidence", 1.0)
        if confidence < self.min_confidence:
            logger.warning(f"置信度低于阈值: {confidence} < {self.min_confidence}")
            return False
        
        # 检查是否有引用来源（如果需要）
        requires_source = context.get("requires_source", False)
        has_source = context.get("has_source", True)
        if requires_source and not has_source:
            logger.warning("需要引用来源但未提供")
            return False
        
        return True


class ResponsivenessRule(Rule):
    """响应性规则"""
    def __init__(self, description: str = "控制系统响应时间"):
        super().__init__("responsiveness", description, priority=80)
        self.max_response_time = 30  # 最大响应时间（秒）
    
    def check(self, context: Dict[str, Any]) -> bool:
        """检查响应时间是否符合要求"""
        self.last_checked = time.time()
        
        # 检查响应时间
        start_time = context.get("start_time")
        if start_time:
            elapsed = time.time() - start_time
            if elapsed > self.max_response_time:
                logger.warning(f"响应时间过长: {elapsed:.2f}秒 > {self.max_response_time}秒")
                # 注意：这里返回True是因为即使超时也应该返回结果，只是记录警告
                # 在实际应用中可以根据需求决定是否返回False
        
        return True


class CoordinationRule(Rule):
    """协调规则"""
    def __init__(self, description: str = "规范智能体间交互"):
        super().__init__("coordination", description, priority=70)
    
    def check(self, context: Dict[str, Any]) -> bool:
        """检查智能体交互是否符合协调规则"""
        self.last_checked = time.time()
        
        # 检查是否通过决策中心进行协调
        communication_path = context.get("communication_path", [])
        if len(communication_path) > 1:
            # 检查是否通过决策中心
            if "决策与调度中心" not in communication_path:
                logger.warning("智能体间直接通信，未通过决策中心")
                # 在实际应用中可以根据需求决定是否严格禁止直接通信
        
        return True


class TransparencyRule(Rule):
    """透明度规则"""
    def __init__(self, description: str = "确保系统行为可解释"):
        super().__init__("transparency", description, priority=60)
    
    def check(self, context: Dict[str, Any]) -> bool:
        """检查系统行为是否透明可解释"""
        self.last_checked = time.time()
        
        # 检查是否无法回答时提供了原因
        action = context.get("action")
        if action == "cannot_answer":
            reason = context.get("reason")
            if not reason:
                logger.warning("无法回答问题但未提供原因")
                return False
        
        # 检查是否提供了决策依据
        if context.get("requires_explanation", False):
            explanation = context.get("explanation")
            if not explanation:
                logger.warning("需要提供解释但未提供")
                return False
        
        return True


class SafetyRule(Rule):
    """安全规则"""
    def __init__(self, description: str = "防止有害内容和攻击"):
        super().__init__("safety", description, priority=110)  # 安全规则优先级最高
        # 简单的有害内容关键词列表
        self.harmful_keywords = [
            "攻击", "病毒", "木马", "破解", "窃取", "诈骗"
        ]
    
    def check(self, context: Dict[str, Any]) -> bool:
        """检查是否包含有害内容"""
        self.last_checked = time.time()
        
        # 检查文本内容
        text = context.get("text", "").lower()
        for keyword in self.harmful_keywords:
            if keyword in text:
                logger.warning(f"检测到潜在有害内容: {keyword}")
                return False
        
        # 检查请求来源（可选）
        request_source = context.get("request_source")
        blocked_sources = context.get("blocked_sources", [])
        if request_source in blocked_sources:
            logger.warning(f"请求来自被阻止的来源: {request_source}")
            return False
        
        return True


class RuleEngine:
    """规则引擎"""
    def __init__(self, rules_config: Dict[str, str]):
        self.logger = logging.getLogger("规则引擎")
        self.rules_config = rules_config
        self.rules: List[Rule] = []
        self.violations: List[Dict[str, Any]] = []
        self._initialize_rules()
        self.logger.info(f"规则引擎初始化完成，加载了 {len(self.rules)} 条规则")
    
    def _initialize_rules(self):
        """初始化规则列表"""
        # 创建规则实例
        rule_classes = {
            "confidentiality": ConfidentialityRule,
            "accuracy": AccuracyRule,
            "responsiveness": ResponsivenessRule,
            "coordination": CoordinationRule,
            "transparency": TransparencyRule,
            "safety": SafetyRule
        }
        
        # 加载配置的规则
        for rule_name, description in self.rules_config.items():
            if rule_name in rule_classes:
                rule_class = rule_classes[rule_name]
                self.rules.append(rule_class(description))
            else:
                # 对于未预定义的规则，创建通用规则
                self.rules.append(Rule(rule_name, description))
        
        # 按优先级排序（优先级高的先执行）
        self.rules.sort(key=lambda r: r.priority, reverse=True)
    
    def check_rules(self, context: Dict[str, Any]) -> bool:
        """检查所有规则"""
        self.violations.clear()
        all_passed = True
        
        for rule in self.rules:
            try:
                passed = rule.check(context)
                if not passed:
                    all_passed = False
                    violation = {
                        "rule": rule.name,
                        "message": rule.get_violation_message(),
                        "timestamp": time.time()
                    }
                    self.violations.append(violation)
                    self.logger.warning(f"规则违反: {rule.name} - {violation['message']}")
            except Exception as e:
                self.logger.error(f"规则检查出错: {rule.name} - {str(e)}", exc_info=True)
        
        return all_passed
    
    def get_violations(self) -> List[Dict[str, Any]]:
        """获取规则违反记录"""
        return self.violations
    
    def add_custom_rule(self, rule_name: str, description: str, 
                       check_func: Callable[[Dict[str, Any]], bool],
                       priority: int = 50):
        """添加自定义规则"""
        class CustomRule(Rule):
            def __init__(self, name, desc, func, prio):
                super().__init__(name, desc, prio)
                self.check_func = func
            
            def check(self, context: Dict[str, Any]) -> bool:
                return self.check_func(context)
        
        custom_rule = CustomRule(rule_name, description, check_func, priority)
        self.rules.append(custom_rule)
        # 重新排序
        self.rules.sort(key=lambda r: r.priority, reverse=True)
        self.logger.info(f"添加自定义规则: {rule_name}")
    
    def get_rule_status(self) -> Dict[str, Any]:
        """获取规则状态统计"""
        status = {
            "total_rules": len(self.rules),
            "rule_details": []
        }
        
        for rule in self.rules:
            status["rule_details"].append({
                "name": rule.name,
                "description": rule.description,
                "priority": rule.priority,
                "last_checked": rule.last_checked
            })
        
        return status
    
    def should_block_action(self, context: Dict[str, Any]) -> bool:
        """判断是否应该阻止当前操作"""
        # 检查安全规则（优先级最高）
        for rule in self.rules:
            if rule.name == "safety":
                try:
                    if not rule.check(context):
                        return True
                except Exception as e:
                    self.logger.error(f"安全规则检查出错: {str(e)}")
                    # 出错时默认阻止操作
                    return True
        
        # 根据其他规则决定是否阻止
        # 在实际应用中可以根据业务需求定制此逻辑
        return False